0.1 Import Data

# load wealingNES package
library(weanlingNES)

# load dataset
data("data_nes")
data("data_ses")

# merge into one dataset
data_comp <- rbind(
  rbindlist(data_nes$year_2018) %>%
    .[, sp := "nes"],
  rbindlist(data_ses$year_2014) %>%
    .[, sp := "ses"],
  use.names = T,
  fill = T
)

0.2 Plots

Let’s try to recreate the same plots Grecian, et al. (2022) did to compare the evolution of some behavioral parameters across time between nes and ses.

0.2.1 Max Depth

p1 <- plot_comp(data_comp[phase == "day", ], "maxdepth", nb_days = 300) +
  labs(
    x = "# days since departure",
    y = "Maximum Depth (m)",
    title = "Day"
  ) +
  scale_y_continuous(limits = c(0, data_comp[, max(maxdepth)])) +
  theme_jjo()
p2 <- plot_comp(data_comp[phase == "night", ], "maxdepth", nb_days = 300) +
  labs(
    x = "# days since departure",
    y = "Maximum Depth (m)",
    title = "Night"
  ) +
  scale_y_continuous(limits = c(0, data_comp[, max(maxdepth)])) +
  theme_jjo() +
  theme(
    axis.title.y = element_blank(),
    axis.ticks.y = element_blank(),
    axis.text.y = element_blank()
  )
ggarrange(p1, p2, ncol = 2, common.legend = TRUE, legend = "bottom")
Estimated temporal changes in maximum depth (m)

Figure 1: Estimated temporal changes in maximum depth (m)

0.2.2 Dive Duration

p1 <- plot_comp(data_comp[phase == "day", ], "dduration", nb_days = 300) +
  labs(
    x = "# days since departure",
    y = "Dive Duration (s)",
    title = "Day"
  ) +
  scale_y_continuous(limits = c(0, data_comp[, quantile(dduration,0.99)])) +
  theme_jjo()
p2 <- plot_comp(data_comp[phase == "night", ], "dduration", nb_days = 200) +
  labs(
    x = "# days since departure",
    y = "Dive Duration (s)",
    title = "Night"
  ) +
  scale_y_continuous(limits = c(0, data_comp[, quantile(dduration,0.99)])) +
  theme_jjo() +
  theme(
    axis.title.y = element_blank(),
    axis.ticks.y = element_blank(),
    axis.text.y = element_blank()
  )
ggarrange(p1, p2, ncol = 2, common.legend = TRUE, legend = "bottom")
Estimated temporal changes in dive duration (s)

Figure 2: Estimated temporal changes in dive duration (s)

0.2.3 “bADL”

# data nes
days_to_keep_nes = data_comp[sp=="nes",
                                .(nb_dives = .N),
                                by = .(.id, day_departure)] %>%
  .[nb_dives >= 50,]
# keep only those days
data_nes_complete_day = merge(data_comp[sp == "nes",],
                                      days_to_keep_nes,
                                      by = c(".id", "day_departure"))
# data ses
days_to_keep_ses = data_comp[sp=="ses",
                                .(nb_dives = .N),
                                by = .(.id, day_departure)] %>%
  .[nb_dives >= 8,]
# keep only those days
data_ses_complete_day = merge(data_comp[sp == "ses",],
                                      days_to_keep_ses,
                                      by = c(".id", "day_departure"))
# data plot
dataPlot = rbind(data_nes_complete_day[divetype=="1: foraging",
                                         .(badl = quantile(dduration, 0.95)),
                                         by = .(.id, day_departure, sp)],
                 data_ses_complete_day[divetype=="1: foraging",
                                         .(badl = quantile(dduration, 0.95)),
                                         by = .(.id, day_departure, sp)])

# comparative plot
plot_comp(dataPlot, "badl", nb_days = 300, alpha_point = .1) +
  labs(
    x = "# days since departure",
    y = "bADL (s)",
    title = "Day"
  ) +
  scale_y_continuous(limits = c(0, dataPlot[, quantile(badl,0.99)])) +
  theme_jjo()
Estimated temporal changes in bADL (s)

Figure 3: Estimated temporal changes in bADL (s)

0.2.4 Drift Rate

# calculate drift rate per day, id and sp
dataPlot = data_comp[divetype == "2: drift",
  .(driftrate = quantile(driftrate, 0.5)),
  by = .(day_departure, .id, sp)
]

# comparative plot
p1 = plot_comp(dataPlot, "driftrate", nb_days = 300, alpha_point = .1) +
  labs(
    x = "# days since departure",
    y = "Drift Rate (m/s)",
    title = "Day"
  ) +
  theme_jjo() +
  theme(legend.position = "bottom")
p2 = ggplot(dataPlot, aes(x = day_departure, y = driftrate, col = .id)) +
  geom_point(show.legend = FALSE) +
  facet_grid(sp~.) +
  theme_jjo() +
  theme(axis.title.y = element_blank())
ggarrange(p1, p2, ncol = 2)
Estimated temporal changes in drift rate (m/s)

Figure 4: Estimated temporal changes in drift rate (m/s)

It’s weird that there is still a bimodality in the maxdepth’s distribution for northern elephant seal, even after splitting day and night.

To investigate why is that, let’s try several representation of this data for the individual 2018070 (nes).

# let's pick an individual
data_test <- data_comp[.id == "ind_2018070", ]

# first we average `lightatsurf` by individuals, day since departure and hour
dataPlot <- data_test[, .(lightatsurf = median(lightatsurf, na.rm = T),
                          phase = first(phase)),
                      by = .(.id,
                             day_departure,
                             date = as.Date(date),
                             hour)]

# then we choose the variable to represent
i <- "maxdepth"
ggplot(data = melt(data_test[, .(.id, date, get(i), phase)],
                   id.vars = c(".id",
                               "date",
                               "phase")),
       aes(x = as.Date(date),
           y = value,
           col = phase)) +
  geom_point(alpha = 1 / 10,
             size = .5) +
  facet_wrap(. ~ .id, scales = "free") +
  scale_x_date(date_labels = "%m/%Y") +
  labs(x = "Date", y = i) +
  theme_jjo() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
        legend.position = "bottom") +
  guides(colour = guide_legend(override.aes = list(size = 7,
                                                   alpha = 1)))
Evolution of the maximum depth reached across time for the individual 2018070

Figure 5: Evolution of the maximum depth reached across time for the individual 2018070

For this individual we can see that there are still a lot of shallow dives during the day. I first thought it was because this individual would probably have started reaching shallow water earlier in the day, at dusk, rather than waiting for complete darkness. To test this hypothesis, I tried to visualize the maxdepth over an entire day throughout the trip.

# this is art!
htmltools::tagList(list(
plot_ly() %>%
  add_trace(
    data = data_test,
    x = ~hour,
    y = ~day_departure,
    z = ~ -maxdepth,
    marker = list(
      size = 1,
      opacity = 0.5
    ),
    mode = "markers",
    type = "scatter3d",
    text = ~divenumber
  ) %>%
  add_trace(
    x = ~hour,
    y = ~day_departure,
    z = ~ (lightatsurf / 200) * 20,
    intensity = ~ lightatsurf / 200,
    data = dataPlot,
    type = "mesh3d",
    showlegend = FALSE
  ) %>%
  layout(
    scene = list(
      zaxis = list(title = "Maximum depth (m)"),
      yaxis = list(title = "# days since departure"),
      xaxis = list(title = "Hour")
    ),
    legend = list(itemsizing = "constant")
  )))

We can see the bimodality of maxdepth within a day is not related to the time of the day, since swallow and deep dives might both occurred at the same time in the day. Let’s see what happen if we color dives with divetype.

# this is art!
htmltools::tagList(list(
  plot_ly() %>%
  add_trace(
    data = data_test,
    x = ~hour,
    y = ~day_departure,
    z = ~ -maxdepth,
    color = ~divetype,
    marker = list(
      size = 1,
      opacity = 0.5
    ),
    mode = "markers",
    type = "scatter3d",
    text = ~divenumber
  ) %>%
  add_trace(
    x = ~hour,
    y = ~day_departure,
    z = ~ (lightatsurf / 200) * 20,
    intensity = ~ lightatsurf / 200,
    data = dataPlot,
    type = "mesh3d",
    showlegend = FALSE
  ) %>%
  layout(
    scene = list(
      zaxis = list(title = "Maximum depth (m)"),
      yaxis = list(title = "# days since departure"),
      xaxis = list(title = "Hour")
    ),
    legend = list(itemsizing = "constant")
  )
))

Well it seems that the bimodality observed in the distribution of maxdepth is mostly explained by divetype, with transit dives occurring at deeper dives that foraging and drift dives (at least for northern elephant seal). We can actually look at the same result with a simple 2D plot:

ggplot(
  data = melt(data_test[, .(.id, date, get(i), divetype)],
              id.vars = c(
                ".id",
                "date",
                "divetype"
              )
  ),
  aes(
    x = as.Date(date),
    y = value,
    col = divetype
  )
) +
  geom_point(
    alpha = 1 / 10,
    size = .5
  ) +
  facet_wrap(. ~ .id, scales = "free") +
  scale_x_date(date_labels = "%m/%Y") +
  labs(x = "Date", y = i) +
  theme_jjo() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = "bottom"
  ) +
  guides(colour = guide_legend(override.aes = list(
    size = 7,
    alpha = 1
  )))
Kind of the same graph, but without looking at the hour of the day

Figure 6: Kind of the same graph, but without looking at the hour of the day

And in bonus, we can add the bathymetry to the 3D plot.

htmltools::tagList(list(
  plot_ly() %>%
  add_trace(
    data = data_test,
    x = ~hour,
    y = ~day_departure,
    z = ~ -maxdepth,
    color = ~divetype,
    marker = list(
      size = 1,
      opacity = 0.5
    ),
    mode = "markers",
    type = "scatter3d",
    text = ~divenumber
  ) %>%
  add_trace(
    x = ~hour,
    y = ~day_departure,
    z = ~ (lightatsurf / 200) * 20,
    intensity = ~ lightatsurf / 200,
    data = dataPlot,
    type = "mesh3d",
    showlegend = FALSE
  ) %>%
  add_trace(
    x = ~hour,
    y = ~day_departure,
    z = ~bathy,
    data = data_test,
    type = "mesh3d"
  ) %>%
  layout(
    scene = list(
      zaxis = list(title = "Maximum depth (m)"),
      yaxis = list(title = "# days since departure"),
      xaxis = list(title = "Hour")
    ),
    legend = list(itemsizing = "constant")
  )))

What about Southern Elephant Seals ?!?

To investigate why is that, let’s try several representation of this data for the individual 140059 (ses).

# let's pick an individual
data_test <- data_comp[.id == "ind_140059",]

# first we average `lightatsurf` by individuals, day since departure and hour
dataPlot <- data_test[, .(lightatsurf = median(lightatsurf, na.rm = T),
                          phase = first(phase)),
                      by = .(.id,
                             day_departure,
                             date = as.Date(date),
                             hour)]

# then we choose the variable to represent
i <- "maxdepth"
ggplot(data = melt(data_test[, .(.id, date, get(i), phase)],
                   id.vars = c(".id",
                               "date",
                               "phase")),
       aes(x = as.Date(date),
           y = value,
           col = phase)) +
  geom_point(alpha = 1 / 5,
             size = .5) +
  facet_wrap(. ~ .id, scales = "free") +
  scale_x_date(date_labels = "%m/%Y") +
  labs(x = "Date", y = i) +
  theme_jjo() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
        legend.position = "bottom") +
  guides(colour = guide_legend(override.aes = list(size = 7,
                                                   alpha = 1)))
Evolution of the maximum depth reached across time for the individual 140059

Figure 7: Evolution of the maximum depth reached across time for the individual 140059

For this individual we can see that until the half of its trip, there is no distinction between day and night in terms of maxdepth. But After, he starts to dive deeper during the day, and shallower during the night. Contrary to the previous nes individual, there seems to be a clear pattern. Let’s look at the graph in 3D:

# this is art!
htmltools::tagList(list(
  plot_ly() %>%
  add_trace(
    data = data_test,
    x = ~hour,
    y = ~day_departure,
    z = ~ -maxdepth,
    marker = list(
      size = 1,
      opacity = 0.8
    ),
    mode = "markers",
    type = "scatter3d",
    text = ~divenumber
  ) %>%
  add_trace(
    x = ~hour,
    y = ~day_departure,
    z = ~ (hour * 0.1) + 20,
    intensity = ~phase_bool,
    data = dataPlot[][, phase_bool := fifelse(phase == "night", 0, 1)][],
    type = "mesh3d",
    showlegend = FALSE
  ) %>%
  layout(
    scene = list(
      zaxis = list(title = "Maximum depth (m)"),
      yaxis = list(title = "# days since departure"),
      xaxis = list(title = "Hour")
    ),
    legend = list(itemsizing = "constant")
  )))

We can clearly see that pass half of its trip, this individual starts to dive deeper during the day. Let’s see what happen if we color dives with divetype.

# this is art!
htmltools::tagList(list(
  plot_ly() %>%
  add_trace(
    data = data_test,
    x = ~hour,
    y = ~day_departure,
    z = ~ -maxdepth,
    color = ~divetype,
    marker = list(
      size = 1,
      opacity = 0.8
    ),
    mode = "markers",
    type = "scatter3d",
    text = ~divenumber
  ) %>%
  add_trace(
    x = ~hour,
    y = ~day_departure,
    z = ~ (hour * 0.1) + 20,
    intensity = ~phase_bool,
    data = dataPlot[][, phase_bool := fifelse(phase == "night", 0, 1)][],
    type = "mesh3d",
    showlegend = FALSE
  ) %>%
  layout(
    scene = list(
      zaxis = list(title = "Maximum depth (m)"),
      yaxis = list(title = "# days since departure"),
      xaxis = list(title = "Hour")
    ),
    legend = list(itemsizing = "constant")
  )
))

It’s hard to tell something, most of the dives seem to be foraging dives, and follow the pattern identified previously. The other interesting results would be a lot of benthic dives at the beginning, and drift dives occurring mostly during the day. Let’s look at a simple 2D plot:

ggplot(
  data = melt(data_test[, .(.id, date, get(i), divetype)],
              id.vars = c(
                ".id",
                "date",
                "divetype"
              )
  ),
  aes(
    x = as.Date(date),
    y = value,
    col = divetype
  )
) +
  geom_point(
    alpha = 1 / 5,
    size = .5
  ) +
  facet_wrap(. ~ .id, scales = "free") +
  scale_x_date(date_labels = "%m/%Y") +
  labs(x = "Date", y = i) +
  theme_jjo() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = "bottom"
  ) +
  guides(colour = guide_legend(override.aes = list(
    size = 7,
    alpha = 1
  )))
Kind of the same graph, but without looking at the hour of the day

Figure 8: Kind of the same graph, but without looking at the hour of the day

And in bonus, we can add the bathymetry to the 3D plot.

htmltools::tagList(list(plot_ly() %>%
  add_trace(
    data = data_test,
    x = ~hour,
    y = ~day_departure,
    z = ~ -maxdepth,
    color = ~divetype,
    marker = list(
      size = 1,
      opacity = 0.8
    ),
    mode = "markers",
    type = "scatter3d",
    text = ~divenumber
  ) %>%
  add_trace(
    x = ~hour,
    y = ~day_departure,
    z = ~ (lightatsurf / 200) * 20,
    intensity = ~ lightatsurf / 200,
    data = dataPlot,
    type = "mesh3d",
    showlegend = FALSE
  ) %>%
  add_trace(
    x = ~hour,
    y = ~day_departure,
    z = ~bathy,
    data = data_test,
    type = "mesh3d"
  ) %>%
  layout(
    scene = list(
      zaxis = list(title = "Maximum depth (m)"),
      yaxis = list(title = "# days since departure"),
      xaxis = list(title = "Hour")
    ),
    legend = list(itemsizing = "constant")
  )))
LS0tCnRpdGxlOiAiRGF0YSBDb21wYXJpc29uIC0gTkVTIHZzIFNFUyAoV0lQKSIKYXV0aG9yOiAiSm9mZnJleSBKT1VNQUEiCmRhdGU6ICJgciBpbnZpc2libGUoU3lzLnNldGxvY2FsZShsb2NhbGUgPSAnQycpKTsgZm9ybWF0KFN5cy5EYXRlKCksIGZvcm1hdCA9ICclQiAlZCwgJVknKWAiCm91dHB1dDoKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICBjc3M6IGNvc21vX2N1c3RvbS5jc3MKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGRmX3ByaW50OiBkZWZhdWx0CiAgICBmaWdfY2FwdGlvbjogeWVzCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogeWVzCiAgICAgIHNtb290aF9zY3JvbGw6IG5vCnZpZ25ldHRlOiA+CiAgJVxWaWduZXR0ZUluZGV4RW50cnl7RGF0YSBDb21wYXJpc29uIC0gTkVTIHZzIFNFUyAoV0lQKX0KICAlXFZpZ25ldHRlRW5naW5le2tuaXRyOjpybWFya2Rvd259CiAgJVxWaWduZXR0ZUVuY29kaW5ne1VURi04fQotLS0KCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KIyBjb21tYW5kIHRvIGJ1aWxkIHBhY2thZ2Ugd2l0aG91dCBnZXR0aW5nIHZpZ25ldHRlIGVycm9yCiMgaHR0cHM6Ly9naXRodWIuY29tL3JzdHVkaW8vcmVudi9pc3N1ZXMvODMzCiMgZGV2dG9vbHM6OmNoZWNrKGJ1aWxkX2FyZ3M9YygiLS1uby1idWlsZC12aWduZXR0ZXMiKSkKCiMgIyByZWR1Y2UgcG5nIHNpemUKIyBrbml0cjo6a25pdF9ob29rcyRzZXQob3B0aXBuZyA9IGtuaXRyOjpob29rX29wdGlwbmcpCiMga25pdHI6OmtuaXRfaG9va3Mkc2V0KHBuZ3F1YW50ID0ga25pdHI6Omhvb2tfcG5ncXVhbnQpCgojIGdsb2JhbCBvcHRpb24gcmVsYXRpdmUgdG8gcm1hcmtkb3duCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICBlY2hvID0gVFJVRSwKICBmaWcuYWxpZ24gPSAiY2VudGVyIiwKICBvdXQud2lkdGggPSAiMTAwJSIsCiAgbWVzc2FnZSA9IEZBTFNFLAogIHdhcm5pbmcgPSBGQUxTRSwKICBjYWNoZS5sYXp5ID0gRkFMU0UsCiAgb3B0aXBuZyA9ICItbzcgLXF1aWV0IiwKICBwbmdxdWFudCA9ICItLXNwZWVkPTEiCikKCiMgbGlicmFyeQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShrYWJsZUV4dHJhKQpsaWJyYXJ5KGNvcnJwbG90KQpsaWJyYXJ5KG1hZ3JpdHRyKQpsaWJyYXJ5KGdncHVicikKbGlicmFyeShwbG90bHkpCgojIHJlbW92ZSBzb21lIHdhcm5pbmdzCnN1cHByZXNzV2FybmluZ3MobGlicmFyeShnZ3Bsb3QyKSkKCiMgZGVmaW5lIG15IG93biB0YWJsZSBmb3JtYXQ6IGh0dHBzOi8vZ2l0aHViLmNvbS9oYW96aHUyMzMva2FibGVFeHRyYS9pc3N1ZXMvMzc0CnNhYmxlIDwtIGZ1bmN0aW9uKHgsIGVzY2FwZSA9IFQsIC4uLikgewogIGtuaXRyOjprYWJsZSh4LCBlc2NhcGUgPSBlc2NhcGUsIC4uLikgJT4lCiAgICBrYWJsZV9zdHlsaW5nKAogICAgICBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAicmVzcG9uc2l2ZSIpLAogICAgICBmdWxsX3dpZHRoID0gRgogICAgKQp9CmBgYAoKIyMgSW1wb3J0IERhdGEKCmBgYHtyfQojIGxvYWQgd2VhbGluZ05FUyBwYWNrYWdlCmxpYnJhcnkod2VhbmxpbmdORVMpCgojIGxvYWQgZGF0YXNldApkYXRhKCJkYXRhX25lcyIpCmRhdGEoImRhdGFfc2VzIikKCiMgbWVyZ2UgaW50byBvbmUgZGF0YXNldApkYXRhX2NvbXAgPC0gcmJpbmQoCiAgcmJpbmRsaXN0KGRhdGFfbmVzJHllYXJfMjAxOCkgJT4lCiAgICAuWywgc3AgOj0gIm5lcyJdLAogIHJiaW5kbGlzdChkYXRhX3NlcyR5ZWFyXzIwMTQpICU+JQogICAgLlssIHNwIDo9ICJzZXMiXSwKICB1c2UubmFtZXMgPSBULAogIGZpbGwgPSBUCikKYGBgCgojIyBQbG90cyB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KCkxldCdzIHRyeSB0byByZWNyZWF0ZSB0aGUgc2FtZSBwbG90cyBbR3JlY2lhbiwgKmV0IGFsLiogKDIwMjIpXShodHRwczovL2RvaS5vcmcvMTAuMTA5OC9yc29zLjIxMTA0MikgZGlkIHRvIGNvbXBhcmUgdGhlIGV2b2x1dGlvbiBvZiBzb21lIGJlaGF2aW9yYWwgcGFyYW1ldGVycyBhY3Jvc3MgdGltZSBiZXR3ZWVuIG5lcyBhbmQgc2VzLgoKIyMjIE1heCBEZXB0aAoKYGBge3IgZmlnLmNhcD0iRXN0aW1hdGVkIHRlbXBvcmFsIGNoYW5nZXMgaW4gbWF4aW11bSBkZXB0aCAobSkifQpwMSA8LSBwbG90X2NvbXAoZGF0YV9jb21wW3BoYXNlID09ICJkYXkiLCBdLCAibWF4ZGVwdGgiLCBuYl9kYXlzID0gMzAwKSArCiAgbGFicygKICAgIHggPSAiIyBkYXlzIHNpbmNlIGRlcGFydHVyZSIsCiAgICB5ID0gIk1heGltdW0gRGVwdGggKG0pIiwKICAgIHRpdGxlID0gIkRheSIKICApICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCBkYXRhX2NvbXBbLCBtYXgobWF4ZGVwdGgpXSkpICsKICB0aGVtZV9qam8oKQpwMiA8LSBwbG90X2NvbXAoZGF0YV9jb21wW3BoYXNlID09ICJuaWdodCIsIF0sICJtYXhkZXB0aCIsIG5iX2RheXMgPSAzMDApICsKICBsYWJzKAogICAgeCA9ICIjIGRheXMgc2luY2UgZGVwYXJ0dXJlIiwKICAgIHkgPSAiTWF4aW11bSBEZXB0aCAobSkiLAogICAgdGl0bGUgPSAiTmlnaHQiCiAgKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgZGF0YV9jb21wWywgbWF4KG1heGRlcHRoKV0pKSArCiAgdGhlbWVfampvKCkgKwogIHRoZW1lKAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCkKICApCmdnYXJyYW5nZShwMSwgcDIsIG5jb2wgPSAyLCBjb21tb24ubGVnZW5kID0gVFJVRSwgbGVnZW5kID0gImJvdHRvbSIpCmBgYAoKIyMjIERpdmUgRHVyYXRpb24KCmBgYHtyIGZpZy5jYXA9IkVzdGltYXRlZCB0ZW1wb3JhbCBjaGFuZ2VzIGluIGRpdmUgZHVyYXRpb24gKHMpIn0KcDEgPC0gcGxvdF9jb21wKGRhdGFfY29tcFtwaGFzZSA9PSAiZGF5IiwgXSwgImRkdXJhdGlvbiIsIG5iX2RheXMgPSAzMDApICsKICBsYWJzKAogICAgeCA9ICIjIGRheXMgc2luY2UgZGVwYXJ0dXJlIiwKICAgIHkgPSAiRGl2ZSBEdXJhdGlvbiAocykiLAogICAgdGl0bGUgPSAiRGF5IgogICkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIGRhdGFfY29tcFssIHF1YW50aWxlKGRkdXJhdGlvbiwwLjk5KV0pKSArCiAgdGhlbWVfampvKCkKcDIgPC0gcGxvdF9jb21wKGRhdGFfY29tcFtwaGFzZSA9PSAibmlnaHQiLCBdLCAiZGR1cmF0aW9uIiwgbmJfZGF5cyA9IDIwMCkgKwogIGxhYnMoCiAgICB4ID0gIiMgZGF5cyBzaW5jZSBkZXBhcnR1cmUiLAogICAgeSA9ICJEaXZlIER1cmF0aW9uIChzKSIsCiAgICB0aXRsZSA9ICJOaWdodCIKICApICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCBkYXRhX2NvbXBbLCBxdWFudGlsZShkZHVyYXRpb24sMC45OSldKSkgKwogIHRoZW1lX2pqbygpICsKICB0aGVtZSgKICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpCiAgKQpnZ2FycmFuZ2UocDEsIHAyLCBuY29sID0gMiwgY29tbW9uLmxlZ2VuZCA9IFRSVUUsIGxlZ2VuZCA9ICJib3R0b20iKQpgYGAKCiMjIyAiYkFETCIKCmBgYHtyIGZpZy5jYXA9IkVzdGltYXRlZCB0ZW1wb3JhbCBjaGFuZ2VzIGluIGJBREwgKHMpIn0KIyBkYXRhIG5lcwpkYXlzX3RvX2tlZXBfbmVzID0gZGF0YV9jb21wW3NwPT0ibmVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuKG5iX2RpdmVzID0gLk4pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gLiguaWQsIGRheV9kZXBhcnR1cmUpXSAlPiUKICAuW25iX2RpdmVzID49IDUwLF0KIyBrZWVwIG9ubHkgdGhvc2UgZGF5cwpkYXRhX25lc19jb21wbGV0ZV9kYXkgPSBtZXJnZShkYXRhX2NvbXBbc3AgPT0gIm5lcyIsXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXlzX3RvX2tlZXBfbmVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gYygiLmlkIiwgImRheV9kZXBhcnR1cmUiKSkKIyBkYXRhIHNlcwpkYXlzX3RvX2tlZXBfc2VzID0gZGF0YV9jb21wW3NwPT0ic2VzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuKG5iX2RpdmVzID0gLk4pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gLiguaWQsIGRheV9kZXBhcnR1cmUpXSAlPiUKICAuW25iX2RpdmVzID49IDgsXQojIGtlZXAgb25seSB0aG9zZSBkYXlzCmRhdGFfc2VzX2NvbXBsZXRlX2RheSA9IG1lcmdlKGRhdGFfY29tcFtzcCA9PSAic2VzIixdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRheXNfdG9fa2VlcF9zZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBjKCIuaWQiLCAiZGF5X2RlcGFydHVyZSIpKQojIGRhdGEgcGxvdApkYXRhUGxvdCA9IHJiaW5kKGRhdGFfbmVzX2NvbXBsZXRlX2RheVtkaXZldHlwZT09IjE6IGZvcmFnaW5nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuKGJhZGwgPSBxdWFudGlsZShkZHVyYXRpb24sIDAuOTUpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IC4oLmlkLCBkYXlfZGVwYXJ0dXJlLCBzcCldLAogICAgICAgICAgICAgICAgIGRhdGFfc2VzX2NvbXBsZXRlX2RheVtkaXZldHlwZT09IjE6IGZvcmFnaW5nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuKGJhZGwgPSBxdWFudGlsZShkZHVyYXRpb24sIDAuOTUpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IC4oLmlkLCBkYXlfZGVwYXJ0dXJlLCBzcCldKQoKIyBjb21wYXJhdGl2ZSBwbG90CnBsb3RfY29tcChkYXRhUGxvdCwgImJhZGwiLCBuYl9kYXlzID0gMzAwLCBhbHBoYV9wb2ludCA9IC4xKSArCiAgbGFicygKICAgIHggPSAiIyBkYXlzIHNpbmNlIGRlcGFydHVyZSIsCiAgICB5ID0gImJBREwgKHMpIiwKICAgIHRpdGxlID0gIkRheSIKICApICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCBkYXRhUGxvdFssIHF1YW50aWxlKGJhZGwsMC45OSldKSkgKwogIHRoZW1lX2pqbygpCmBgYAoKIyMjIERyaWZ0IFJhdGUKCmBgYHtyIGZpZy5jYXA9IkVzdGltYXRlZCB0ZW1wb3JhbCBjaGFuZ2VzIGluIGRyaWZ0IHJhdGUgKG0vcykifQojIGNhbGN1bGF0ZSBkcmlmdCByYXRlIHBlciBkYXksIGlkIGFuZCBzcApkYXRhUGxvdCA9IGRhdGFfY29tcFtkaXZldHlwZSA9PSAiMjogZHJpZnQiLAogIC4oZHJpZnRyYXRlID0gcXVhbnRpbGUoZHJpZnRyYXRlLCAwLjUpKSwKICBieSA9IC4oZGF5X2RlcGFydHVyZSwgLmlkLCBzcCkKXQoKIyBjb21wYXJhdGl2ZSBwbG90CnAxID0gcGxvdF9jb21wKGRhdGFQbG90LCAiZHJpZnRyYXRlIiwgbmJfZGF5cyA9IDMwMCwgYWxwaGFfcG9pbnQgPSAuMSkgKwogIGxhYnMoCiAgICB4ID0gIiMgZGF5cyBzaW5jZSBkZXBhcnR1cmUiLAogICAgeSA9ICJEcmlmdCBSYXRlIChtL3MpIiwKICAgIHRpdGxlID0gIkRheSIKICApICsKICB0aGVtZV9qam8oKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpCnAyID0gZ2dwbG90KGRhdGFQbG90LCBhZXMoeCA9IGRheV9kZXBhcnR1cmUsIHkgPSBkcmlmdHJhdGUsIGNvbCA9IC5pZCkpICsKICBnZW9tX3BvaW50KHNob3cubGVnZW5kID0gRkFMU0UpICsKICBmYWNldF9ncmlkKHNwfi4pICsKICB0aGVtZV9qam8oKSArCiAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpKQpnZ2FycmFuZ2UocDEsIHAyLCBuY29sID0gMikKYGBgCgojIyB7LnVubGlzdGVkIC51bm51bWJlcmVkfQoKPiBJdCdzIHdlaXJkIHRoYXQgdGhlcmUgaXMgc3RpbGwgYSBiaW1vZGFsaXR5IGluIHRoZSBgbWF4ZGVwdGhgJ3MgZGlzdHJpYnV0aW9uIGZvciBub3J0aGVybiBlbGVwaGFudCBzZWFsLCBldmVuIGFmdGVyIHNwbGl0dGluZyBgZGF5YCBhbmQgYG5pZ2h0YC4KClRvIGludmVzdGlnYXRlIHdoeSBpcyB0aGF0LCBsZXQncyB0cnkgc2V2ZXJhbCByZXByZXNlbnRhdGlvbiBvZiB0aGlzIGRhdGEgZm9yIHRoZSBpbmRpdmlkdWFsIGAyMDE4MDcwYCAobmVzKS4KCmBgYHtyIGZpZy5jYXA9IkV2b2x1dGlvbiBvZiB0aGUgbWF4aW11bSBkZXB0aCByZWFjaGVkIGFjcm9zcyB0aW1lIGZvciB0aGUgaW5kaXZpZHVhbCAyMDE4MDcwIn0KIyBsZXQncyBwaWNrIGFuIGluZGl2aWR1YWwKZGF0YV90ZXN0IDwtIGRhdGFfY29tcFsuaWQgPT0gImluZF8yMDE4MDcwIiwgXQoKIyBmaXJzdCB3ZSBhdmVyYWdlIGBsaWdodGF0c3VyZmAgYnkgaW5kaXZpZHVhbHMsIGRheSBzaW5jZSBkZXBhcnR1cmUgYW5kIGhvdXIKZGF0YVBsb3QgPC0gZGF0YV90ZXN0WywgLihsaWdodGF0c3VyZiA9IG1lZGlhbihsaWdodGF0c3VyZiwgbmEucm0gPSBUKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBwaGFzZSA9IGZpcnN0KHBoYXNlKSksCiAgICAgICAgICAgICAgICAgICAgICBieSA9IC4oLmlkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRheV9kZXBhcnR1cmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0ZSA9IGFzLkRhdGUoZGF0ZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG91cildCgojIHRoZW4gd2UgY2hvb3NlIHRoZSB2YXJpYWJsZSB0byByZXByZXNlbnQKaSA8LSAibWF4ZGVwdGgiCmdncGxvdChkYXRhID0gbWVsdChkYXRhX3Rlc3RbLCAuKC5pZCwgZGF0ZSwgZ2V0KGkpLCBwaGFzZSldLAogICAgICAgICAgICAgICAgICAgaWQudmFycyA9IGMoIi5pZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZGF0ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAicGhhc2UiKSksCiAgICAgICBhZXMoeCA9IGFzLkRhdGUoZGF0ZSksCiAgICAgICAgICAgeSA9IHZhbHVlLAogICAgICAgICAgIGNvbCA9IHBoYXNlKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAxIC8gMTAsCiAgICAgICAgICAgICBzaXplID0gLjUpICsKICBmYWNldF93cmFwKC4gfiAuaWQsIHNjYWxlcyA9ICJmcmVlIikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2xhYmVscyA9ICIlbS8lWSIpICsKICBsYWJzKHggPSAiRGF0ZSIsIHkgPSBpKSArCiAgdGhlbWVfampvKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZSA9IDcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gMSkpKQpgYGAKCkZvciB0aGlzIGluZGl2aWR1YWwgd2UgY2FuIHNlZSB0aGF0IHRoZXJlIGFyZSBzdGlsbCBhIGxvdCBvZiBzaGFsbG93IGRpdmVzIGR1cmluZyB0aGUgZGF5LiBJIGZpcnN0IHRob3VnaHQgaXQgd2FzIGJlY2F1c2UgdGhpcyBpbmRpdmlkdWFsIHdvdWxkIHByb2JhYmx5IGhhdmUgc3RhcnRlZCByZWFjaGluZyBzaGFsbG93IHdhdGVyIGVhcmxpZXIgaW4gdGhlIGRheSwgYXQgZHVzaywgcmF0aGVyIHRoYW4gd2FpdGluZyBmb3IgY29tcGxldGUgZGFya25lc3MuIFRvIHRlc3QgdGhpcyBoeXBvdGhlc2lzLCBJIHRyaWVkIHRvIHZpc3VhbGl6ZSB0aGUgYG1heGRlcHRoYCBvdmVyIGFuIGVudGlyZSBkYXkgdGhyb3VnaG91dCB0aGUgdHJpcC4gCgpgYGB7ciBmaWcuY2FwPSJNYXhpbXVtIGRlcHRoIGluIGZ1bmN0aW9uIG9mIHRoZSBudW1iZXIgb2YgZGF5cyBzaW5jZSBkZXBhcnR1cmUgYW5kIHRoZSBob3VyIG9mIHRoZSBkYXkgZm9yIGluZF8yMDE4MDcwIChuZXMpLiBUaGUgMi1EIHBsYW5lIGFsbG93IHRvIGlkZW50aWZ5IGRheSBhbmQgbmlnaHQgYmFzZWQgb24gbGlnaHQgbGV2ZWwifQojIHRoaXMgaXMgYXJ0IQpodG1sdG9vbHM6OnRhZ0xpc3QobGlzdCgKcGxvdF9seSgpICU+JQogIGFkZF90cmFjZSgKICAgIGRhdGEgPSBkYXRhX3Rlc3QsCiAgICB4ID0gfmhvdXIsCiAgICB5ID0gfmRheV9kZXBhcnR1cmUsCiAgICB6ID0gfiAtbWF4ZGVwdGgsCiAgICBtYXJrZXIgPSBsaXN0KAogICAgICBzaXplID0gMSwKICAgICAgb3BhY2l0eSA9IDAuNQogICAgKSwKICAgIG1vZGUgPSAibWFya2VycyIsCiAgICB0eXBlID0gInNjYXR0ZXIzZCIsCiAgICB0ZXh0ID0gfmRpdmVudW1iZXIKICApICU+JQogIGFkZF90cmFjZSgKICAgIHggPSB+aG91ciwKICAgIHkgPSB+ZGF5X2RlcGFydHVyZSwKICAgIHogPSB+IChsaWdodGF0c3VyZiAvIDIwMCkgKiAyMCwKICAgIGludGVuc2l0eSA9IH4gbGlnaHRhdHN1cmYgLyAyMDAsCiAgICBkYXRhID0gZGF0YVBsb3QsCiAgICB0eXBlID0gIm1lc2gzZCIsCiAgICBzaG93bGVnZW5kID0gRkFMU0UKICApICU+JQogIGxheW91dCgKICAgIHNjZW5lID0gbGlzdCgKICAgICAgemF4aXMgPSBsaXN0KHRpdGxlID0gIk1heGltdW0gZGVwdGggKG0pIiksCiAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICIjIGRheXMgc2luY2UgZGVwYXJ0dXJlIiksCiAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJIb3VyIikKICAgICksCiAgICBsZWdlbmQgPSBsaXN0KGl0ZW1zaXppbmcgPSAiY29uc3RhbnQiKQogICkpKQpgYGAKCldlIGNhbiBzZWUgdGhlIGJpbW9kYWxpdHkgb2YgYG1heGRlcHRoYCB3aXRoaW4gYSBkYXkgaXMgbm90IHJlbGF0ZWQgdG8gdGhlIHRpbWUgb2YgdGhlIGRheSwgc2luY2Ugc3dhbGxvdyBhbmQgZGVlcCBkaXZlcyBtaWdodCBib3RoIG9jY3VycmVkIGF0IHRoZSBzYW1lIHRpbWUgaW4gdGhlIGRheS4gTGV0J3Mgc2VlIHdoYXQgaGFwcGVuIGlmIHdlIGNvbG9yIGRpdmVzIHdpdGggYGRpdmV0eXBlYC4KCmBgYHtyIGZpZy5jYXA9IlNhbWUgZ3JhcGggYnV0IHdpdGggYG1heGRlcHRoYCBjb2xvcmVkIGJ5IGBkaXZldHlwZWAifQojIHRoaXMgaXMgYXJ0IQpodG1sdG9vbHM6OnRhZ0xpc3QobGlzdCgKICBwbG90X2x5KCkgJT4lCiAgYWRkX3RyYWNlKAogICAgZGF0YSA9IGRhdGFfdGVzdCwKICAgIHggPSB+aG91ciwKICAgIHkgPSB+ZGF5X2RlcGFydHVyZSwKICAgIHogPSB+IC1tYXhkZXB0aCwKICAgIGNvbG9yID0gfmRpdmV0eXBlLAogICAgbWFya2VyID0gbGlzdCgKICAgICAgc2l6ZSA9IDEsCiAgICAgIG9wYWNpdHkgPSAwLjUKICAgICksCiAgICBtb2RlID0gIm1hcmtlcnMiLAogICAgdHlwZSA9ICJzY2F0dGVyM2QiLAogICAgdGV4dCA9IH5kaXZlbnVtYmVyCiAgKSAlPiUKICBhZGRfdHJhY2UoCiAgICB4ID0gfmhvdXIsCiAgICB5ID0gfmRheV9kZXBhcnR1cmUsCiAgICB6ID0gfiAobGlnaHRhdHN1cmYgLyAyMDApICogMjAsCiAgICBpbnRlbnNpdHkgPSB+IGxpZ2h0YXRzdXJmIC8gMjAwLAogICAgZGF0YSA9IGRhdGFQbG90LAogICAgdHlwZSA9ICJtZXNoM2QiLAogICAgc2hvd2xlZ2VuZCA9IEZBTFNFCiAgKSAlPiUKICBsYXlvdXQoCiAgICBzY2VuZSA9IGxpc3QoCiAgICAgIHpheGlzID0gbGlzdCh0aXRsZSA9ICJNYXhpbXVtIGRlcHRoIChtKSIpLAogICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiIyBkYXlzIHNpbmNlIGRlcGFydHVyZSIpLAogICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiSG91ciIpCiAgICApLAogICAgbGVnZW5kID0gbGlzdChpdGVtc2l6aW5nID0gImNvbnN0YW50IikKICApCikpCmBgYAoKV2VsbCBpdCBzZWVtcyB0aGF0IHRoZSBiaW1vZGFsaXR5IG9ic2VydmVkIGluIHRoZSBkaXN0cmlidXRpb24gb2YgYG1heGRlcHRoYCBpcyBtb3N0bHkgZXhwbGFpbmVkIGJ5IGBkaXZldHlwZWAsIHdpdGggKnRyYW5zaXQqIGRpdmVzIG9jY3VycmluZyBhdCBkZWVwZXIgZGl2ZXMgdGhhdCAqZm9yYWdpbmcqIGFuZCAqZHJpZnQqIGRpdmVzIChhdCBsZWFzdCBmb3Igbm9ydGhlcm4gZWxlcGhhbnQgc2VhbCkuIFdlIGNhbiBhY3R1YWxseSBsb29rIGF0IHRoZSBzYW1lIHJlc3VsdCB3aXRoIGEgc2ltcGxlIDJEIHBsb3Q6CgpgYGB7ciBmaWcuY2FwPSJLaW5kIG9mIHRoZSBzYW1lIGdyYXBoLCBidXQgd2l0aG91dCBsb29raW5nIGF0IHRoZSBob3VyIG9mIHRoZSBkYXkifQpnZ3Bsb3QoCiAgZGF0YSA9IG1lbHQoZGF0YV90ZXN0WywgLiguaWQsIGRhdGUsIGdldChpKSwgZGl2ZXR5cGUpXSwKICAgICAgICAgICAgICBpZC52YXJzID0gYygKICAgICAgICAgICAgICAgICIuaWQiLAogICAgICAgICAgICAgICAgImRhdGUiLAogICAgICAgICAgICAgICAgImRpdmV0eXBlIgogICAgICAgICAgICAgICkKICApLAogIGFlcygKICAgIHggPSBhcy5EYXRlKGRhdGUpLAogICAgeSA9IHZhbHVlLAogICAgY29sID0gZGl2ZXR5cGUKICApCikgKwogIGdlb21fcG9pbnQoCiAgICBhbHBoYSA9IDEgLyAxMCwKICAgIHNpemUgPSAuNQogICkgKwogIGZhY2V0X3dyYXAoLiB+IC5pZCwgc2NhbGVzID0gImZyZWUiKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfbGFiZWxzID0gIiVtLyVZIikgKwogIGxhYnMoeCA9ICJEYXRlIiwgeSA9IGkpICsKICB0aGVtZV9qam8oKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIKICApICsKICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoCiAgICBzaXplID0gNywKICAgIGFscGhhID0gMQogICkpKQpgYGAKCkFuZCBpbiBib251cywgd2UgY2FuIGFkZCB0aGUgYmF0aHltZXRyeSB0byB0aGUgM0QgcGxvdC4KCmBgYHtyIGZpZy5jYXA9IlRoaXMgaXMgYXJ0ISJ9Cmh0bWx0b29sczo6dGFnTGlzdChsaXN0KAogIHBsb3RfbHkoKSAlPiUKICBhZGRfdHJhY2UoCiAgICBkYXRhID0gZGF0YV90ZXN0LAogICAgeCA9IH5ob3VyLAogICAgeSA9IH5kYXlfZGVwYXJ0dXJlLAogICAgeiA9IH4gLW1heGRlcHRoLAogICAgY29sb3IgPSB+ZGl2ZXR5cGUsCiAgICBtYXJrZXIgPSBsaXN0KAogICAgICBzaXplID0gMSwKICAgICAgb3BhY2l0eSA9IDAuNQogICAgKSwKICAgIG1vZGUgPSAibWFya2VycyIsCiAgICB0eXBlID0gInNjYXR0ZXIzZCIsCiAgICB0ZXh0ID0gfmRpdmVudW1iZXIKICApICU+JQogIGFkZF90cmFjZSgKICAgIHggPSB+aG91ciwKICAgIHkgPSB+ZGF5X2RlcGFydHVyZSwKICAgIHogPSB+IChsaWdodGF0c3VyZiAvIDIwMCkgKiAyMCwKICAgIGludGVuc2l0eSA9IH4gbGlnaHRhdHN1cmYgLyAyMDAsCiAgICBkYXRhID0gZGF0YVBsb3QsCiAgICB0eXBlID0gIm1lc2gzZCIsCiAgICBzaG93bGVnZW5kID0gRkFMU0UKICApICU+JQogIGFkZF90cmFjZSgKICAgIHggPSB+aG91ciwKICAgIHkgPSB+ZGF5X2RlcGFydHVyZSwKICAgIHogPSB+YmF0aHksCiAgICBkYXRhID0gZGF0YV90ZXN0LAogICAgdHlwZSA9ICJtZXNoM2QiCiAgKSAlPiUKICBsYXlvdXQoCiAgICBzY2VuZSA9IGxpc3QoCiAgICAgIHpheGlzID0gbGlzdCh0aXRsZSA9ICJNYXhpbXVtIGRlcHRoIChtKSIpLAogICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiIyBkYXlzIHNpbmNlIGRlcGFydHVyZSIpLAogICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiSG91ciIpCiAgICApLAogICAgbGVnZW5kID0gbGlzdChpdGVtc2l6aW5nID0gImNvbnN0YW50IikKICApKSkKYGBgCgo+IFdoYXQgYWJvdXQgU291dGhlcm4gRWxlcGhhbnQgU2VhbHMgPyE/CgpUbyBpbnZlc3RpZ2F0ZSB3aHkgaXMgdGhhdCwgbGV0J3MgdHJ5IHNldmVyYWwgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBkYXRhIGZvciB0aGUgaW5kaXZpZHVhbCBgMTQwMDU5YCAoc2VzKS4KCgpgYGB7ciBmaWcuY2FwPSJFdm9sdXRpb24gb2YgdGhlIG1heGltdW0gZGVwdGggcmVhY2hlZCBhY3Jvc3MgdGltZSBmb3IgdGhlIGluZGl2aWR1YWwgMTQwMDU5In0KIyBsZXQncyBwaWNrIGFuIGluZGl2aWR1YWwKZGF0YV90ZXN0IDwtIGRhdGFfY29tcFsuaWQgPT0gImluZF8xNDAwNTkiLF0KCiMgZmlyc3Qgd2UgYXZlcmFnZSBgbGlnaHRhdHN1cmZgIGJ5IGluZGl2aWR1YWxzLCBkYXkgc2luY2UgZGVwYXJ0dXJlIGFuZCBob3VyCmRhdGFQbG90IDwtIGRhdGFfdGVzdFssIC4obGlnaHRhdHN1cmYgPSBtZWRpYW4obGlnaHRhdHN1cmYsIG5hLnJtID0gVCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGhhc2UgPSBmaXJzdChwaGFzZSkpLAogICAgICAgICAgICAgICAgICAgICAgYnkgPSAuKC5pZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXlfZGVwYXJ0dXJlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGUgPSBhcy5EYXRlKGRhdGUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvdXIpXQoKIyB0aGVuIHdlIGNob29zZSB0aGUgdmFyaWFibGUgdG8gcmVwcmVzZW50CmkgPC0gIm1heGRlcHRoIgpnZ3Bsb3QoZGF0YSA9IG1lbHQoZGF0YV90ZXN0WywgLiguaWQsIGRhdGUsIGdldChpKSwgcGhhc2UpXSwKICAgICAgICAgICAgICAgICAgIGlkLnZhcnMgPSBjKCIuaWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImRhdGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInBoYXNlIikpLAogICAgICAgYWVzKHggPSBhcy5EYXRlKGRhdGUpLAogICAgICAgICAgIHkgPSB2YWx1ZSwKICAgICAgICAgICBjb2wgPSBwaGFzZSkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMSAvIDUsCiAgICAgICAgICAgICBzaXplID0gLjUpICsKICBmYWNldF93cmFwKC4gfiAuaWQsIHNjYWxlcyA9ICJmcmVlIikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2xhYmVscyA9ICIlbS8lWSIpICsKICBsYWJzKHggPSAiRGF0ZSIsIHkgPSBpKSArCiAgdGhlbWVfampvKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZSA9IDcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gMSkpKQpgYGAKCkZvciB0aGlzIGluZGl2aWR1YWwgd2UgY2FuIHNlZSB0aGF0IHVudGlsIHRoZSBoYWxmIG9mIGl0cyB0cmlwLCB0aGVyZSBpcyBubyBkaXN0aW5jdGlvbiBiZXR3ZWVuIGRheSBhbmQgbmlnaHQgaW4gdGVybXMgb2YgYG1heGRlcHRoYC4gQnV0IEFmdGVyLCBoZSBzdGFydHMgdG8gZGl2ZSBkZWVwZXIgZHVyaW5nIHRoZSBkYXksIGFuZCBzaGFsbG93ZXIgZHVyaW5nIHRoZSBuaWdodC4gQ29udHJhcnkgdG8gdGhlIHByZXZpb3VzIG5lcyBpbmRpdmlkdWFsLCB0aGVyZSBzZWVtcyB0byBiZSBhIGNsZWFyIHBhdHRlcm4uIExldCdzIGxvb2sgYXQgdGhlIGdyYXBoIGluIDNEOgoKYGBge3IgZmlnLmNhcD0iTWF4aW11bSBkZXB0aCBpbiBmdW5jdGlvbiBvZiB0aGUgbnVtYmVyIG9mIGRheXMgc2luY2UgZGVwYXJ0dXJlIGFuZCB0aGUgaG91ciBvZiB0aGUgZGF5IGZvciBpbmRfMTQwMDU5IChzZXMpLiBUaGUgMi1EIHBsYW5lIGFsbG93IHRvIGlkZW50aWZ5IGRheSBhbmQgbmlnaHQgYmFzZWQgb24gdGltZSBhbmQgbG9jYXRpb24uIn0KIyB0aGlzIGlzIGFydCEKaHRtbHRvb2xzOjp0YWdMaXN0KGxpc3QoCiAgcGxvdF9seSgpICU+JQogIGFkZF90cmFjZSgKICAgIGRhdGEgPSBkYXRhX3Rlc3QsCiAgICB4ID0gfmhvdXIsCiAgICB5ID0gfmRheV9kZXBhcnR1cmUsCiAgICB6ID0gfiAtbWF4ZGVwdGgsCiAgICBtYXJrZXIgPSBsaXN0KAogICAgICBzaXplID0gMSwKICAgICAgb3BhY2l0eSA9IDAuOAogICAgKSwKICAgIG1vZGUgPSAibWFya2VycyIsCiAgICB0eXBlID0gInNjYXR0ZXIzZCIsCiAgICB0ZXh0ID0gfmRpdmVudW1iZXIKICApICU+JQogIGFkZF90cmFjZSgKICAgIHggPSB+aG91ciwKICAgIHkgPSB+ZGF5X2RlcGFydHVyZSwKICAgIHogPSB+IChob3VyICogMC4xKSArIDIwLAogICAgaW50ZW5zaXR5ID0gfnBoYXNlX2Jvb2wsCiAgICBkYXRhID0gZGF0YVBsb3RbXVssIHBoYXNlX2Jvb2wgOj0gZmlmZWxzZShwaGFzZSA9PSAibmlnaHQiLCAwLCAxKV1bXSwKICAgIHR5cGUgPSAibWVzaDNkIiwKICAgIHNob3dsZWdlbmQgPSBGQUxTRQogICkgJT4lCiAgbGF5b3V0KAogICAgc2NlbmUgPSBsaXN0KAogICAgICB6YXhpcyA9IGxpc3QodGl0bGUgPSAiTWF4aW11bSBkZXB0aCAobSkiKSwKICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIiMgZGF5cyBzaW5jZSBkZXBhcnR1cmUiKSwKICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIkhvdXIiKQogICAgKSwKICAgIGxlZ2VuZCA9IGxpc3QoaXRlbXNpemluZyA9ICJjb25zdGFudCIpCiAgKSkpCmBgYAoKV2UgY2FuIGNsZWFybHkgc2VlIHRoYXQgcGFzcyBoYWxmIG9mIGl0cyB0cmlwLCB0aGlzIGluZGl2aWR1YWwgc3RhcnRzIHRvIGRpdmUgZGVlcGVyIGR1cmluZyB0aGUgZGF5LiBMZXQncyBzZWUgd2hhdCBoYXBwZW4gaWYgd2UgY29sb3IgZGl2ZXMgd2l0aCBgZGl2ZXR5cGVgLgoKYGBge3IgZmlnLmNhcD0iU2FtZSBncmFwaCBidXQgd2l0aCBgbWF4ZGVwdGhgIGNvbG9yZWQgYnkgYGRpdmV0eXBlYCJ9CiMgdGhpcyBpcyBhcnQhCmh0bWx0b29sczo6dGFnTGlzdChsaXN0KAogIHBsb3RfbHkoKSAlPiUKICBhZGRfdHJhY2UoCiAgICBkYXRhID0gZGF0YV90ZXN0LAogICAgeCA9IH5ob3VyLAogICAgeSA9IH5kYXlfZGVwYXJ0dXJlLAogICAgeiA9IH4gLW1heGRlcHRoLAogICAgY29sb3IgPSB+ZGl2ZXR5cGUsCiAgICBtYXJrZXIgPSBsaXN0KAogICAgICBzaXplID0gMSwKICAgICAgb3BhY2l0eSA9IDAuOAogICAgKSwKICAgIG1vZGUgPSAibWFya2VycyIsCiAgICB0eXBlID0gInNjYXR0ZXIzZCIsCiAgICB0ZXh0ID0gfmRpdmVudW1iZXIKICApICU+JQogIGFkZF90cmFjZSgKICAgIHggPSB+aG91ciwKICAgIHkgPSB+ZGF5X2RlcGFydHVyZSwKICAgIHogPSB+IChob3VyICogMC4xKSArIDIwLAogICAgaW50ZW5zaXR5ID0gfnBoYXNlX2Jvb2wsCiAgICBkYXRhID0gZGF0YVBsb3RbXVssIHBoYXNlX2Jvb2wgOj0gZmlmZWxzZShwaGFzZSA9PSAibmlnaHQiLCAwLCAxKV1bXSwKICAgIHR5cGUgPSAibWVzaDNkIiwKICAgIHNob3dsZWdlbmQgPSBGQUxTRQogICkgJT4lCiAgbGF5b3V0KAogICAgc2NlbmUgPSBsaXN0KAogICAgICB6YXhpcyA9IGxpc3QodGl0bGUgPSAiTWF4aW11bSBkZXB0aCAobSkiKSwKICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIiMgZGF5cyBzaW5jZSBkZXBhcnR1cmUiKSwKICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIkhvdXIiKQogICAgKSwKICAgIGxlZ2VuZCA9IGxpc3QoaXRlbXNpemluZyA9ICJjb25zdGFudCIpCiAgKQopKQpgYGAKCkl0J3MgaGFyZCB0byB0ZWxsIHNvbWV0aGluZywgbW9zdCBvZiB0aGUgZGl2ZXMgc2VlbSB0byBiZSBmb3JhZ2luZyBkaXZlcywgYW5kIGZvbGxvdyB0aGUgcGF0dGVybiBpZGVudGlmaWVkIHByZXZpb3VzbHkuIFRoZSBvdGhlciBpbnRlcmVzdGluZyByZXN1bHRzIHdvdWxkIGJlIGEgbG90IG9mIGJlbnRoaWMgZGl2ZXMgYXQgdGhlIGJlZ2lubmluZywgYW5kIGRyaWZ0IGRpdmVzIG9jY3VycmluZyBtb3N0bHkgZHVyaW5nIHRoZSBkYXkuIExldCdzIGxvb2sgYXQgYSBzaW1wbGUgMkQgcGxvdDoKCmBgYHtyIGZpZy5jYXA9IktpbmQgb2YgdGhlIHNhbWUgZ3JhcGgsIGJ1dCB3aXRob3V0IGxvb2tpbmcgYXQgdGhlIGhvdXIgb2YgdGhlIGRheSJ9CmdncGxvdCgKICBkYXRhID0gbWVsdChkYXRhX3Rlc3RbLCAuKC5pZCwgZGF0ZSwgZ2V0KGkpLCBkaXZldHlwZSldLAogICAgICAgICAgICAgIGlkLnZhcnMgPSBjKAogICAgICAgICAgICAgICAgIi5pZCIsCiAgICAgICAgICAgICAgICAiZGF0ZSIsCiAgICAgICAgICAgICAgICAiZGl2ZXR5cGUiCiAgICAgICAgICAgICAgKQogICksCiAgYWVzKAogICAgeCA9IGFzLkRhdGUoZGF0ZSksCiAgICB5ID0gdmFsdWUsCiAgICBjb2wgPSBkaXZldHlwZQogICkKKSArCiAgZ2VvbV9wb2ludCgKICAgIGFscGhhID0gMSAvIDUsCiAgICBzaXplID0gLjUKICApICsKICBmYWNldF93cmFwKC4gfiAuaWQsIHNjYWxlcyA9ICJmcmVlIikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2xhYmVscyA9ICIlbS8lWSIpICsKICBsYWJzKHggPSAiRGF0ZSIsIHkgPSBpKSArCiAgdGhlbWVfampvKCkgKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iCiAgKSArCiAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KAogICAgc2l6ZSA9IDcsCiAgICBhbHBoYSA9IDEKICApKSkKYGBgCgpBbmQgaW4gYm9udXMsIHdlIGNhbiBhZGQgdGhlIGJhdGh5bWV0cnkgdG8gdGhlIDNEIHBsb3QuCgpgYGB7ciBmaWcuY2FwPSJUaGlzIGlzIGFydCEifQpodG1sdG9vbHM6OnRhZ0xpc3QobGlzdChwbG90X2x5KCkgJT4lCiAgYWRkX3RyYWNlKAogICAgZGF0YSA9IGRhdGFfdGVzdCwKICAgIHggPSB+aG91ciwKICAgIHkgPSB+ZGF5X2RlcGFydHVyZSwKICAgIHogPSB+IC1tYXhkZXB0aCwKICAgIGNvbG9yID0gfmRpdmV0eXBlLAogICAgbWFya2VyID0gbGlzdCgKICAgICAgc2l6ZSA9IDEsCiAgICAgIG9wYWNpdHkgPSAwLjgKICAgICksCiAgICBtb2RlID0gIm1hcmtlcnMiLAogICAgdHlwZSA9ICJzY2F0dGVyM2QiLAogICAgdGV4dCA9IH5kaXZlbnVtYmVyCiAgKSAlPiUKICBhZGRfdHJhY2UoCiAgICB4ID0gfmhvdXIsCiAgICB5ID0gfmRheV9kZXBhcnR1cmUsCiAgICB6ID0gfiAobGlnaHRhdHN1cmYgLyAyMDApICogMjAsCiAgICBpbnRlbnNpdHkgPSB+IGxpZ2h0YXRzdXJmIC8gMjAwLAogICAgZGF0YSA9IGRhdGFQbG90LAogICAgdHlwZSA9ICJtZXNoM2QiLAogICAgc2hvd2xlZ2VuZCA9IEZBTFNFCiAgKSAlPiUKICBhZGRfdHJhY2UoCiAgICB4ID0gfmhvdXIsCiAgICB5ID0gfmRheV9kZXBhcnR1cmUsCiAgICB6ID0gfmJhdGh5LAogICAgZGF0YSA9IGRhdGFfdGVzdCwKICAgIHR5cGUgPSAibWVzaDNkIgogICkgJT4lCiAgbGF5b3V0KAogICAgc2NlbmUgPSBsaXN0KAogICAgICB6YXhpcyA9IGxpc3QodGl0bGUgPSAiTWF4aW11bSBkZXB0aCAobSkiKSwKICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIiMgZGF5cyBzaW5jZSBkZXBhcnR1cmUiKSwKICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIkhvdXIiKQogICAgKSwKICAgIGxlZ2VuZCA9IGxpc3QoaXRlbXNpemluZyA9ICJjb25zdGFudCIpCiAgKSkpCmBgYCAgCg==